/* eslint-disable */
import Base64 from './btoa.js'

const btoa = str => Base64.btoa(str);

const BASE64_MAPPING = [
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
  'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
  'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  'w', 'x', 'y', 'z', '0', '1', '2', '3',
  '4', '5', '6', '7', '8', '9', '+', '/'
];
/**
 *ascii convert to binary
 */
const _toBinary = function(ascii) {
  const binary = new Array();
  while (ascii > 0) {
    const b = ascii % 2;
    ascii = Math.floor(ascii / 2);
    binary.push(b);
  }

  binary.reverse();
  return binary;
};

/**
 *binary convert to decimal
 */
const _toDecimal = function(binary) {
  let dec = 0;
  let p = 0;
  for (let i = binary.length - 1; i >= 0; --i) {
    const b = binary[i];
    if (b === 1) {
      dec += Math.pow(2, p);
    }
    ++p;
  }
  return dec;
};

/**
 *unicode convert to utf-8
 */
const _toUTF8Binary = function(c, binaryArray) {
  const mustLen = (8 - (c + 1)) + ((c - 1) * 6);
  const fatLen = binaryArray.length;
  let diff = mustLen - fatLen;
  while (--diff >= 0) {
    binaryArray.unshift(0);
  }
  const binary = [];
  let _c = c;
  while (--_c >= 0) {
    binary.push(1);
  }
  binary.push(0);
  let i = 0,
    len = 8 - (c + 1);
  for (; i < len; ++i) {
    binary.push(binaryArray[i]);
  }

  for (let j = 0; j < c - 1; ++j) {
    binary.push(1);
    binary.push(0);
    let sum = 6;
    while (--sum >= 0) {
      binary.push(binaryArray[i++]);
    }
  }
  return binary;
};

const __BASE64 = {
  // 使用btoa和atob来进行Base64转码和解码
  hexToBase64(hexstring) {
    return btoa(hexstring.match(/\w{2}/g).map(a => String.fromCharCode(parseInt(a, 16))).join('')).replace(/[\/]/g, '_').replace(/[+]/g, '-').replace(/[=]/g, '');
  },
  /**
   *BASE64 Encode
   */
  encoder(str) {
    const base64_Index = [];
    let binaryArray = [];
    for (let i = 0, len = str.length; i < len; ++i) {
      const unicode = str.charCodeAt(i);
      const _tmpBinary = _toBinary(unicode);
      if (unicode < 0x80) {
        let _tmpdiff = 8 - _tmpBinary.length;
        while (--_tmpdiff >= 0) {
          _tmpBinary.unshift(0);
        }
        binaryArray = binaryArray.concat(_tmpBinary);
      } else if (unicode >= 0x80 && unicode <= 0x7FF) {
        binaryArray = binaryArray.concat(_toUTF8Binary(2, _tmpBinary));
      } else if (unicode >= 0x800 && unicode <= 0xFFFF) { // UTF-8 3byte
        binaryArray = binaryArray.concat(_toUTF8Binary(3, _tmpBinary));
      } else if (unicode >= 0x10000 && unicode <= 0x1FFFFF) { // UTF-8 4byte
        binaryArray = binaryArray.concat(_toUTF8Binary(4, _tmpBinary));
      } else if (unicode >= 0x200000 && unicode <= 0x3FFFFFF) { // UTF-8 5byte
        binaryArray = binaryArray.concat(_toUTF8Binary(5, _tmpBinary));
      } else if (unicode >= 4000000 && unicode <= 0x7FFFFFFF) { // UTF-8 6byte
        binaryArray = binaryArray.concat(_toUTF8Binary(6, _tmpBinary));
      }
    }

    let extra_Zero_Count = 0;
    for (let i = 0, len = binaryArray.length; i < len; i += 6) {
      const diff = (i + 6) - len;
      if (diff === 2) {
        extra_Zero_Count = 2;
      } else if (diff === 4) {
        extra_Zero_Count = 4;
      }
      // if(extra_Zero_Count > 0){
      //	len += extra_Zero_Count+1;
      // }
      let _tmpExtra_Zero_Count = extra_Zero_Count;
      while (--_tmpExtra_Zero_Count >= 0) {
        binaryArray.push(0);
      }
      base64_Index.push(_toDecimal(binaryArray.slice(i, i + 6)));
    }

    let base64 = '';
    for (let i = 0, len = base64_Index.length; i < len; ++i) {
      base64 += BASE64_MAPPING[base64_Index[i]];
    }

    for (let i = 0, len = extra_Zero_Count / 2; i < len; ++i) {
      base64 += '=';
    }
    return base64;
  },
  /**
   *BASE64  Decode for UTF-8
   */
  decoder(_base64Str) {
    const _len = _base64Str.length;
    let extra_Zero_Count = 0;
    /**
     *计算在进行BASE64编码的时候，补了几个0
     */
    if (_base64Str.charAt(_len - 1) === '=') {
      // alert(_base64Str.charAt(_len-1));
      // alert(_base64Str.charAt(_len-2));
      if (_base64Str.charAt(_len - 2) === '=') { // 两个等号说明补了4个0
        extra_Zero_Count = 4;
        _base64Str = _base64Str.substring(0, _len - 2);
      } else { // 一个等号说明补了2个0
        extra_Zero_Count = 2;
        _base64Str = _base64Str.substring(0, _len - 1);
      }
    }

    let binaryArray = [];
    for (let i = 0, len = _base64Str.length; i < len; ++i) {
      const c = _base64Str.charAt(i);
      for (let j = 0, size = BASE64_MAPPING.length; j < size; ++j) {
        if (c === BASE64_MAPPING[j]) {
          const _tmp = _toBinary(j);
          /* 不足6位的补0*/
          const _tmpLen = _tmp.length;
          if (6 - _tmpLen > 0) {
            for (let k = 6 - _tmpLen; k > 0; --k) {
              _tmp.unshift(0);
            }
          }
          binaryArray = binaryArray.concat(_tmp);
          break;
        }
      }
    }
    if (extra_Zero_Count > 0) {
      binaryArray = binaryArray.slice(0, binaryArray.length - extra_Zero_Count);
    }
    let unicode = [];
    let unicodeBinary = [];
    for (let i = 0, len = binaryArray.length; i < len;) {
      if (binaryArray[i] === 0) {
        unicode = unicode.concat(_toDecimal(binaryArray.slice(i, i + 8)));
        i += 8;
      } else {
        let sum = 0;
        while (i < len) {
          if (binaryArray[i] === 1) {
            ++sum;
          } else {
            break;
          }
          ++i;
        }
        unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 1, i + 8 - sum));
        i += 8 - sum;
        while (sum > 1) {
          unicodeBinary = unicodeBinary.concat(binaryArray.slice(i + 2, i + 8));
          i += 8;
          --sum;
        }
        unicode = unicode.concat(_toDecimal(unicodeBinary));
        unicodeBinary = [];
      }
    }
    // unicode 转换成字符串
    let str = '';
    for (let i = 0, len = unicode.length; i < len; ++i) {
      str += String.fromCharCode(unicode[i]);
    }
    return str;
  }
};
export default __BASE64;
